#pragma once
// 模拟线程池

#include "Thread.hpp"
#include "Mutex.hpp"
#include <vector>
#include <queue>
#include <unistd.h>

using namespace ThreadNs;

const int gnum = 4;
template <class T>
class ThreadPool;

template <class T>
class ThreadData
{
public:
    ThreadPool<T> *_threadpool;
    std::string _name;

public:
    ThreadData(ThreadPool<T> *tp, const std::string &n)
        : _threadpool(tp), _name(n)
    {
    }
};

template <class T>
class ThreadPool
{
private:
    static void *handlerTask(void *args)
    {
        // 测试
        //  while (true)
        //  {
        //      sleep(1);
        //      std::cout << "thread" << pthread_self() << "run..." <<std::endl;
        //  }
        //  ThreadPool<T> *threadpool = static_cast<ThreadPool*>(args);
        ThreadData<T> *td = static_cast<ThreadData<T> *>(args);
        while (true)
        {
            T t;
            { // 为什么要另行封装，因为静态变量没有this指针，无法直接访问成员变量;
                // 为什么不使用pthread_mutex_lock(&thread->lockQueue->_mutex,nullptr);很简单，代码太长了，而且不易阅读
                //  td->_threadpool->lockQueue();
                LockGuard(td->_threadpool->mutex());
                while (td->_threadpool->isQueueEmpty()) // 如果为空就进行等待
                {
                    td->_threadpool->threadWait();
                }
                t = td->_threadpool->Pop(); // 走到这里事一定能够获取到任务 ----pop的本质是将任务从公共队列当中，拿到当前线程自己独立的栈当中
                // td->_threadpool->unlockQueue();
            }
            std::cout << td->_name << ":获取了一个任务： " << t.toString() << "  并完成了这个任务：" << t() << std::endl; // 执行任务
        }
        delete td;
        return nullptr;
    }

public:
    void lockQueue() { pthread_mutex_lock(&_mutex); }         // 加锁
    void unlockQueue() { pthread_mutex_unlock(&_mutex); }     // 解锁
    bool isQueueEmpty() { return _task_queue.empty(); }       // 判空
    void threadWait() { pthread_cond_wait(&_cond, &_mutex); } // 条件等待
    T Pop()                                                   // 取出任务
    {
        T t = _task_queue.front();
        _task_queue.pop();
        return t;
    }
    pthread_mutex_t *mutex()
    {
        return &_mutex;
    }

public:
    ThreadPool(const int &num_ = gnum)
        : _num(num_)
    {
        pthread_mutex_init(&_mutex, nullptr);
        pthread_cond_init(&_cond, nullptr);
        for (int i = 0; i < _num; i++)
        {
            _threads.push_back(new Thread());
        }
    }

    void run()
    {
        for (const auto &t : _threads)
        {
            ThreadData<T> *td = new ThreadData<T>(this, t->threadname());
            t->start(handlerTask, td);
            std::cout << t->threadname() << "start..." << std::endl;
        }
    }

    void push(const T &in)
    {
        LockGuard lockguard(&_mutex);
        // pthread_mutex_lock(&_mutex);
        _task_queue.push(in);
        // pthread_mutex_unlock(&_mutex);
        pthread_cond_signal(&_cond);
    }

    // void join()
    // {
    //     for(const auto &t : _threads)
    //     {
    //         t->join();
    //         std::cout << t->threadname()<< "join..." << std::endl;
    //     }
    // }

    ~ThreadPool()
    {
        pthread_mutex_destroy(&_mutex);
        pthread_cond_destroy(&_cond);
        for (const auto &t : _threads)
        {
            delete t;
        }
    }

private:
    int _num;                       // 线程池中的线程数量
    std::vector<Thread *> _threads; // 存放线程的数组
    std::queue<T> _task_queue;      // 存放任务的队列
    pthread_mutex_t _mutex;
    pthread_cond_t _cond;
};